#include<iostream>
#include<vector>
#include<list>
#include<map>

  
/***

Definició de tipus per a grafs.

Representem els grafs amb una taula de llistes d'adjacència, fent que els
vèrtexs siguin enters entre 0 i $|V|-1$. Els grafs són dirigits,
però es poden usar com a grafs no dirigits fent que tots
els arcs siguin dobles.

Definim dues macros: ¿forall\_ver(u,G)¿ fa que l'enter ¿u¿ recorri tots els
vèrtexs del graph ¿G¿ i ¿forall\_adj(uv,G[u])¿ fa que l'iterador ¿uv¿ recorri
tota la llista  d'adjacència ¿G[u]¿. En aquest darrer cas, hom es pot imaginar
que ¿u¿ és el vèrtex de sortida, que ¿uv¿ és l'arc i que ¿*uv¿ és el vèrtex de
destí.

***/
#define forall_adj(uv,L) for (arc uv=(L).begin(); uv!=(L).end(); ++uv)
#define forall_ver(u,G) for (int u=0; u<int((G).size()); ++u)

/*
The Input

The input consists of a sequence of one or more postal routes.
A route is composed of a sequence of street names (strings), 
one per line, and is terminated by the string ``deadend'' 
which is NOT part of the route. The first and last letters of each 
street name specify the two intersections for that street, 
the length of the street name indicates the cost of traversing 
the street. All street names will consist of lowercase alphabetic characters.

For example, the name foo indicates a street with intersections 
f and o of length 3, and the name computer indicates a street with
intersections c and r of length 8. No street name will have the same
first and last letter and there will be at most one street directly
connecting any two intersections. As specified, the number of intersections
with odd degree in a postal route will be at most two. In each postal 
route there will be a path between all intersections, i.e., 
the intersections are connected.

The Output1

For each postal route the output should consist of 
the cost of the minimal tour that visits all streets 
at least once. The minimal tour costs should be output 
in the order corresponding to the input postal routes.
*/
using namespace std;
struct aresta2
{
 char v;
 int peso;
};

struct aresta
{
 char u;
 list<aresta2> adjacents;
};

typedef vector<aresta> graph;

void insert(graph &g, char u, char v, int pes)
{
  bool trobat = false;
  int i;
  for (i= 0; i < g.size() and !trobat; i++)
  {
    if(g[i].u == u or g[i].u == v)
    {
      trobat = true;
      aresta2 aux;
      if(g[i].u == u)
      {
	aux.v = v;
	aux.peso = pes;
	g[i].adjacents.push_back(aux);
	int j = 0;
	bool auxtrobat = false;
	for(j = i+1; j < g.size() and !auxtrobat; j++)
	{
	  if(g[i].u == v) auxtrobat = true;
	}
	if(!auxtrobat)
	{
	  g.resize(g.size() + 1);
	  g[g.size()-1].u = v;
	}
      }
      else
      {
	aux.v = u;
	aux.peso = pes;
	g[i].adjacents.push_back(aux);
	bool auxtrobat = false;
	int j = 0;
	for(j = i+1; j < g.size() and !auxtrobat; j++)
	{
	  if(g[i].u == u) auxtrobat = true;
	}
	if(!auxtrobat)
	{
	  g.resize(g.size() + 1);
	  g[g.size()-1].u = u;
	}
      }
    }
  }
  if(!trobat)
  {
    g.resize(g.size() + 1);
    aresta2 aux;
    aux.v = v;
    aux.peso = pes;
    g[g.size()-1].u = u;
    g[g.size()-1].adjacents.push_back(aux);
  }
}

void escribir_grafo(graph g)
{
  for(int i= 0; i < g.size(); i++)
  {
    cout<<g[i].u<<":";
    while(!g[i].adjacents.empty())
    {
      aresta2 aux =g[i].adjacents.front();
      cout<<" "<<aux.v;
      g[i].adjacents.pop_front();
    }
    cout<<endl;
  }
}

int buscarCaminoMinimo(graph g)
{
    for(int i= 0; i < g.size(); i++)
    {
    
    }
}

int main()
{
  
  while(1)
  {
    string street;
    cin>>street;
    graph g(0);
    while(street != "deadend")
    {
      char u = street[0];
      char v = street[street.size()-1];
      insert(g,u,v,street.size());
      cin>>street;
    }
    //int min = buscarCaminoMinimo(g);
    escribir_grafo(g);
  }
}
